package cn.dataling.ai.handler;

import cn.dataling.ai.common.ConstraintViolationTemplate;
import cn.dataling.ai.common.ExceptionCore;
import cn.dataling.ai.common.Response;
import cn.dataling.ai.common.ResponseStatusCodeEnum;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @coder taoym
 * @datetime 2021/6/4 18:16
 * @desc 处理统一异常
 */
@RestControllerAdvice
public class ExceptionHandlerController {

    /**
     * @coder taoym
     * @datetime 2021/6/4 18:16
     * @desc 参数校验捕获器，捕获Validated抛出的异常
     */
    @ExceptionHandler(ValidationException.class)
    public Response<Void> validationException(ValidationException e) {

        if (e instanceof ConstraintViolationException) {
            Set<ConstraintViolation<?>> constraintViolations = ((ConstraintViolationException) e)
                    .getConstraintViolations();
            List<ConstraintViolationTemplate> constraintViolationTemplateList = new ArrayList<>();
            constraintViolations.forEach(f -> {
                ConstraintViolationTemplate constraintViolationTemplate = new ConstraintViolationTemplate();
                String[] attribute = f.getPropertyPath().toString().split("\\.", 2);
                constraintViolationTemplate.setParam(attribute[1]);
                constraintViolationTemplate.setMessage(f.getMessage());
                constraintViolationTemplateList.add(constraintViolationTemplate);
            });
            return Response.fail(ResponseStatusCodeEnum.PARAMETER_VALIDATE_IS_FAIL.getCode(), constraintViolationTemplateList.get(0).getMessage(), "");
        }
        return null;
    }

    /**
     * @coder taoym
     * @datetime 2021/6/4 18:16
     * @desc 参数校验捕获器，捕获get请求的Valid注解抛出的异常
     */
    @ExceptionHandler(BindException.class)
    public Response<Void> bindException(BindException e) {
        List<ConstraintViolationTemplate> constraintViolationTemplateList = new ArrayList<>();
        e.getFieldErrors().forEach(f -> {
            ConstraintViolationTemplate constraintViolationTemplate = new ConstraintViolationTemplate();
            constraintViolationTemplate.setParam(f.getField());
            constraintViolationTemplate.setMessage(f.getDefaultMessage());
            constraintViolationTemplateList.add(constraintViolationTemplate);
        });
        return Response.fail(ResponseStatusCodeEnum.PARAMETER_VALIDATE_IS_FAIL.getCode(), constraintViolationTemplateList.get(0).getMessage(), "");
    }

    /**
     * @coder taoym
     * @datetime 2021/6/4 18:16
     * @desc 参数有校验捕获器，捕获post请求的Valid注解抛出的异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Response<Void> methodArgumentNotValidException(MethodArgumentNotValidException e) {
        List<ConstraintViolationTemplate> constraintViolationTemplateList = new ArrayList<>();
        e.getBindingResult().getFieldErrors().forEach(f -> {
            ConstraintViolationTemplate constraintViolationTemplate = new ConstraintViolationTemplate();
            constraintViolationTemplate.setParam(f.getField());
            constraintViolationTemplate.setMessage(f.getDefaultMessage());
            constraintViolationTemplateList.add(constraintViolationTemplate);
        });
        return Response.fail(ResponseStatusCodeEnum.PARAMETER_VALIDATE_IS_FAIL.getCode(), constraintViolationTemplateList.get(0).getMessage(), "");
    }

    /**
     * @coder taoym
     * @datetime 2021/6/4 18:16
     * @desc 自定义异常拦截器
     */
    @ExceptionHandler(ExceptionCore.class)
    public Response<Void> exceptionCore(ExceptionCore e) {
        return Response.fail(e.getResponseStatusCode(), "");
    }

    /**
     * @coder taoym
     * @datetime 2021/10/8 16:28
     * @desc 拦截 requestParam 的异常
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Response<Void> missingRequestValueException(MissingServletRequestParameterException e) {
        return Response.fail(ResponseStatusCodeEnum.PARAMETER_VALIDATE_IS_FAIL, e.getParameterName() + "不能为空");
    }
}
